<template>
  <div class="ebook-reader">
    <div id="read"></div>
    <div
      class="ebook-reader-mask"
      @click="onMaskClick"
      @touchmove="move"
      @touchend="moveEnd"
      @mousedown.left="onMouseEnter"
      @mousemove.left="onMouseMove"
      @mouseup.left="onMouseEnd"
    ></div>
  </div>
</template>

<script>
import Epub from 'epubjs'
import { ebookMixin } from '@/utils/mixin.js'
import { flatten } from '@/utils/book.js'
import {
  getFontFamily,
  saveFontFamily,
  getFontSize,
  saveFontSize,
  getTheme,
  saveTheme,
  getLocation
} from '@/utils/localStorage'
import { getLocalForage } from '../../utils/localForage'
global.ePub = Epub
export default {
  mixins: [ebookMixin],
  methods: {
    // 1 - 鼠标进入
    // 2 - 鼠标进入后的移动
    // 3 - 鼠标从移动状态松手
    // 4 - 鼠标还原
    onMouseEnter(e) {
      console.log('enter')
      this.mouseState = 1
      this.mouseStartTime = e.timeStamp
      e.preventDefault()
      e.stopPropagation()
    },
    onMouseMove(e) {
      if (this.mouseState === 1) {
        this.mouseState = 2
      } else if (this.mouseState === 2) {
        let offsetY = 0
        if (this.firstOffsetY) {
          offsetY = e.offsetY - this.firstOffsetY
          this.setOffsetY(offsetY)
        } else {
          this.firstOffsetY = e.clientY
          console.log(this.firstOffsetY)
        }
        e.preventDefault()
        e.stopPropagation()
      }
    },
    onMouseEnd(e) {
      if (this.mouseState === 2) {
        // 复位
        this.setOffsetY(0)
        this.firstOffsetY = null
        this.mouseState = 3
      } else {
        // 没有移动鼠标 就调用 onMaskClick 进行上下页
        this.mouseState = 4
      }
      this.mouseEndTime = e.timeStamp
      const time = this.mouseEndTime - this.mouseStartTime
      if (time < 100) {
        this.mouseState = 4
      }
      e.preventDefault()
      e.stopPropagation()
    },
    //   解析和渲染电子书
    initEpub(url) {
      //  1. 获取链接
      // Nginx 服务器路径
      // const url = 'http://localhost:81/epub/' + this.fileName
      // const url = `${process.env.VUE_APP_RES_URL}/epub/${this.fileName}`
      console.log(url)
      // 解析电子书
      this.book = new Epub(url)
      // 将this.book 传入 vuex
      this.setCurrentBook(this.book)
      this.initRendition()
      this.toggleTitleAndMenu()
      this.parseBook()
      // this.initGesture()
      this.book.ready
        .then(() => {
          return this.book.locations.generate(
            750 * (window.innerWidth / 375) * (getFontSize(this.fileName) / 16)
          )
        })
        /**
         * locations分出来每一页以及navigations中目录的某部分相同，
         * 将属于同一章节的页面放到那一章节的对象下，
         * 这样就能统计出每一章有多少页，
         * 显示到侧边栏的目录条目中
         */
        .then((locations) => {
          this.setBookAvailable(true)
          this.navigation.forEach(nav => {
            nav.pagelist = []
          })
          // 每一页的数据
          locations.forEach((item) => {
            const loc = item.match(/\[(.*)\]!/)[1] // 用此结果和href对比
            console.log(loc)
            this.navigation.forEach((nav) => {
              if (nav.href) {
                // xxx.html
                const href = nav.href.match(/^(.*)\.html$/)[1]
                // console.log(href)
                if (href === loc) {
                  // 这里已经将 locations 对应到各个目录和章节中去了
                  nav.pagelist.push(item)
                }
              }
            })
            // 定义初始页数
            let currentPage = 1
            this.navigation.forEach((nav, index) => {
              if (index === 0) {
                // 这是第一页
                nav.page = 1
              } else {
                nav.page = currentPage
              }
              currentPage += nav.pagelist.length + 1
            })
          })
          console.log(this.navigation)
          this.setPagelist(locations)
          // console.log(locations)
          // 分页完成调用 refreshLocation
          this.refreshLocation()
        })
    },
    initRendition() {
      console.log(this.book)
      this.rendition = this.book.renderTo('read', {
        width: window.innerWidth,
        heigth: window.innerHeight,
        // 微信兼容性配置 这样能在微信上正常使用
        // methods: 'default'
        methods: 'scrolled'
      })
      // 通过Rendition.display渲染电子书 返回promise
      // this.rendition.display().then(() => {
      //   this.initThemes()
      //   this.initFontSize()
      //   this.initFontFamily()
      //   // 全局样式切换
      //   this.initGlobalStyle()
      // })
      const location = getLocation(this.fileName)
      console.log(location)
      this.display(location, () => {
        this.initThemes()
        this.initFontSize()
        this.initFontFamily()
        this.initGlobalStyle()
      })
      // 当我们阅读器渲染完毕时 可以获取资源文件时 来调用这个方法
      this.rendition.hooks.content.register((contents) => {
        // 手动添加样式文件
        // 这里不生效 因为 查看 content 源码时 是需要给 url 的 而这里给了路径
        // content.addStylesheet('../../assets/fonts/daysOne.css')
        // 所以我们可以将web字体放在 Nginx服务器上 生成http链接 这样就可以引用了
        // 这里返回promise
        Promise.all([
          contents.addStylesheet(
            `${process.env.VUE_APP_RES_URL}/fonts/daysOne.css`
          ),
          contents.addStylesheet(
            `${process.env.VUE_APP_RES_URL}/fonts/cabin.css`
          ),
          contents.addStylesheet(
            `${process.env.VUE_APP_RES_URL}/fonts/montserrat.css`
          ),
          contents.addStylesheet(
            `${process.env.VUE_APP_RES_URL}/fonts/tangerine.css`
          )
        ]).then(() => {})
      })
    },
    initGesture() {
      // epubjs 提供了 on 方法  touchstart 触摸开始事件
      this.rendition.on('touchstart', (event) => {
        //   changedTouches[0] 取第一只手指
        this.touchStartX = event.changedTouches[0].clientX
        //   获取触摸时间
        this.touchStartTime = event.timeStamp
      })
      // touchend 触摸结束事件
      this.rendition.on('touchend', (event) => {
        //   偏移量
        const offsetX = event.changedTouches[0].clientX - this.touchStartX
        const time = event.timeStamp - this.touchStartTime
        if (time < 500 && offsetX > 40) {
          this.prevPage()
          this.hideTitleAndMenu()
        } else if (time < 500 && offsetX < -40) {
          this.nextPage()
          this.hideTitleAndMenu()
        } else {
          this.toggleTitleAndMenu()
        }
        // 禁止默认操作方法调用
        // event.preventDefault()
        // 禁止冒泡
        event.stopPropagation()
      })
    },
    onMaskClick(e) {
      if (this.mouseState && (this.mouseState === 2 || this.mouseState === 3)) {
        return
      }
      const offsetX = e.clientX
      const width = window.innerWidth
      if (offsetX > 0 && offsetX < width * 0.3) {
        this.prevPage()
      } else if (offsetX > 0 && offsetX > width * 0.7) {
        console.log(offsetX)
        this.nextPage()
      } else {
        this.toggleTitleAndMenu()
      }
    },
    move(e) {
      let offsetY = 0
      if (this.firstOffsetY) {
        offsetY = e.changedTouches[0].clientY - this.firstOffsetY
        // console.log(offsetY)
        this.setOffsetY(offsetY)
      } else {
        this.firstOffsetY = e.changedTouches[0].clientY
      }
      e.preventDefault()
      e.stopPropagation()
    },
    moveEnd(e) {
      // 松手将 offsetY 设为 0
      this.setOffsetY(0)
      this.firstOffsetY = null
    },
    // 左翻页功能
    prevPage() {
      console.log(this.rendition)
      if (this.rendition) {
        this.rendition.prev().then(() => {
          this.refreshLocation()
        })
      }
    },
    // 右翻页功能
    nextPage() {
      if (this.rendition) {
        this.rendition.next().then(() => {
          this.refreshLocation()
        })
      }
    },
    // 显示标题栏和菜单栏
    toggleTitleAndMenu() {
      console.log('显示与隐藏')
      // this.$store.dispatch('setMenuVisible', !this.menuVisible)
      if (this.menuVisible) {
        this.setSettingVisible(-1)
      }
      this.setMenuVisible(!this.menuVisible)
      this.setFontFamilyVisible(false)
    },
    // 隐藏标题栏和菜单栏
    // hideTitleAndMenu() {
    //   // this.$store.dispatch('setMenuVisible', false)
    //   this.setMenuVisible(false)
    //   // 将字号设置隐藏
    //   this.setSettingVisible(-1)
    //   this.setFontFamilyVisible(false)
    // },
    // 注册主题
    initThemes() {
      const defaultTheme = getTheme(this.fileName)
      if (!defaultTheme) {
        // 设置默认主题
        saveTheme(this.fileName, defaultTheme)
      }
      this.setDefaultTheme(defaultTheme)
      console.log(this.themeList)
      this.themeList.forEach((theme) => {
        this.rendition.themes.register(theme.name, theme.style)
      })
      // 默认主题
      this.rendition.themes.select(this.defaultTheme)
      console.log(this.defaultTheme)
    },
    // 根据localStorage来设置字号
    initFontSize() {
      const fontSize = getFontSize(this.fileName)
      console.log(fontSize)
      if (!fontSize) {
        saveFontSize(this.fileName, this.defaultFontSize)
      } else {
        this.currentBook.rendition.themes.fontSize(fontSize + 'px')
        this.setDefaulfFontSize(fontSize)
      }
    },
    // 根据localStorage来设置web字体
    initFontFamily() {
      const fonts = getFontFamily(this.fileName)
      // 当LocalStorage中没有字体时 添加默认字体
      if (!fonts) {
        saveFontFamily(this.fileName, this.defaultFontFamily)
      } else {
        // 当LocalStorage中有字体时
        this.currentBook.rendition.themes.font(fonts)
        this.setDefaultFontFamily(fonts)
        console.log(`LocalStorage中存在字体${fonts}`)
      }
    },
    // 解析电子书内容
    parseBook() {
      // 获取封面信息 loaded 表示电子书正在加载的状态 cover 获取封面加载的信息
      this.book.loaded.cover.then((cover) => {
        // console.log(cover)
        // 此时获取的还不是对象
        // 通过 book的 archive 的 createUrl
        this.book.archive.createUrl(cover).then((url) => {
          // 将封面信息存入vueX
          this.setCover(url)
          console.log(url + '封面信息')
        })
      })
      // 获取标题和作者信息
      this.book.loaded.metadata.then((metadata) => {
        // 将信息存储到vueX
        this.setMetadata(metadata)
        console.log(metadata)
      })
      // 获取目录信息
      this.book.loaded.navigation.then((nav) => {
        // 获取的是多维数组
        // console.log(nav)
        // 处理多维数组
        // console.log(flatten(nav.toc))
        // 将树状结构变为一维数组同时加上level字段
        const navItem = flatten(nav.toc)
        function find(item, level = 0) {
          return !item.parent ? level : find(navItem.filter((parenItem) => parenItem.id === item.parent)[0], ++level)
        }
        navItem.forEach((item) => {
          item.level = find(item)
        })
        console.log(navItem)
        // 存储到vueX
        this.setNavigation(navItem)
      })
    }
  },
  mounted() {
    const books = this.$route.params.fileName.split('|')
    const fileName = books[1]
    getLocalForage(fileName, (err, blob) => {
      if (!err && blob) {
        console.log('找到离线缓存电子书')
        this.setFileName(books.join('/')).then(() => {
          console.log(this.fileName)
          this.initEpub(blob)
        })
      } else {
        console.log('未找到离线缓存,开始下载电子书')
        this.setFileName(books.join('/')).then(() => {
          const url = `${process.env.VUE_APP_EPUB_URL}/${this.fileName}.epub`
          this.initEpub(url)
        })
      }
    })
    /**
     * 根据动态路由来展示电子书 */
    // 考虑到 fileName 到后续有很多地方使用到 所以放在vuex中
    // const fileName = this.$route.params.fileName.split('|').join('/')
    // 解析路由 拼成Nginx目录
    // console.log(`${baseUrl}${fileName}`)
    // setFileName 这里返回了promise 可以用then
    this.setFileName(this.$route.params.fileName.split('|').join('/')).then(() => {
      const url = `${process.env.VUE_APP_RES_URL}/epub/${this.fileName}`
      this.initEpub(url)
    })
  }
}
</script>

<style lang="scss" scoped>
.ebook-reader {
  width: 100%;
  height: 100%;
  overflow: hidden;
  .ebook-reader-mask {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: 100;
  }
}
</style>
